package MainPackage
{
  import flash.events.EventDispatcher;
  import lastfm.LastFm;
  import lastfm.events.LastFmEvent;
  import MainPackage.events.RadioEvent;
  import mx.binding.utils.BindingUtils;
  import mx.binding.utils.ChangeWatcher;
  import vk.RemoteVars;

  /**
   * ...
   * @author Roman Marchenko
   */
  public class Radio extends EventDispatcher
  {
    private const MAX_RECENT_TRACKS:uint = 75; // Max tracks to remember.

    private var _charts:LastFm;
    private var _played:Array;
    private var _recentTracks:Array;

    public var _title:String;

    public function Radio()
    {
    }

    private function onSongsUpdate(event:LastFmEvent):void
    {
      trace("Radio.onSongsUpdate");
      var artist:String = event.artist.toString();
      var track:String = event.song.toString();
      if (_charts.isBanned(artist, track))
      {
        trace("Radio.onSongsUpdate: track is banned");
        nextSong();
        return;
      }

      // Check if the track has been already played recently (last 75 tracks???).
      var entry:String = track.toLowerCase();
      var i:int = _recentTracks.indexOf(entry);
      if (0 <= i)
      {
        trace("Radio.onSongsUpdate: track has been played recently");
        chooseTrackAndLoad(artist);
        return;
      }
      updateRecentTracksList(entry);

      var newevent:RadioEvent = new RadioEvent(RadioEvent.TRACK_UPDATE);
      newevent.artist = event.artist;
      newevent.song = event.song;
      newevent.image = event.image;

      dispatchEvent(newevent);
    }

    public function addBanned(artist:String, track:String):void
    {
      _charts.addBanned(artist, track);
    }

    private function onChartsUpdate(event:LastFmEvent):void
    {
      trace("Radio.onChartsUpdate");
      _title = event.artist;
      nextSong();
    }

    private function updateRecentTracksList(track:String):void
    {
      _recentTracks.unshift(track.toLowerCase());
      if (MAX_RECENT_TRACKS < _recentTracks.length)
      {
        _recentTracks.pop();
      }
    }

    private function onError(event:LastFmEvent):void
    {
      trace("Radio.onError: error: " + event.error);
      var newevent:RadioEvent = new RadioEvent(RadioEvent.ERROR);
      newevent.error = event.error;
      dispatchEvent(newevent);
    }

    private function onArtistNotFound(event:LastFmEvent):void
    {
      trace("Radio.onArtistNotFound: " + event.error);
      var newevent:RadioEvent = new RadioEvent(RadioEvent.ERROR);
      newevent.error = event.error;
      dispatchEvent(newevent);
    }

    private function onRecentTracksUpdate(event:LastFmEvent):void
    {
      trace("Radio.onRecentTracksUpdate");
      if (null == event.recenttracks)
      {
        return;
      }

      for (var i:int = 0; i < event.recenttracks.length; ++i)
      {
        updateRecentTracksList(event.recenttracks[i]);
      }
    }

    public function getShortArtistList():String
    {
      var res:String = "";
      for (var i:int = 0; i < 8 && i < _charts._artists.length; ++i)
      {
        if (0 != i)
        {
          res += ", ";
        }

        res += _charts._artists[i];
      }

      return res;
    }

    private function nextSong():void
    {
      trace("Radio.nextSong");

      // Get next artist.
      var maxArtist:int = _charts._artists.length;
      var maxLastPlayed:int = (maxArtist < 10) ? maxArtist : 10;

      if (_played.length >= maxLastPlayed)
      {
        _played.shift();
      }

      var nextArtist:int = -1;
      do
      {
        nextArtist = Math.floor(Math.random() * maxArtist);
      } while (0 <= _played.indexOf(nextArtist));
      var nextArtistStr:String = _charts._artists[nextArtist];
      trace("Radio.nextSong: artist: " + nextArtistStr);

      _played.push(nextArtist);
      chooseTrackAndLoad(nextArtistStr);
    }

    private function chooseTrackAndLoad(artist:String):void
    {
      // Get next song.
      var nextSong:int = -1;
      var maxSong:int = 10;
      var songmax:int = _charts.getSongMax(artist);
      if (0 <= songmax)
      {
        maxSong = songmax / 10; // Take first 10% of tracks.
      }

      nextSong = Math.floor(Math.random() * maxSong);
      _charts.loadSong(artist, nextSong);
    }

    public function play(artist:String):void
    {
      trace("Radio.play: " + artist);
      _charts = new LastFm;
      _played = new Array;
      _recentTracks = new Array;

      _charts.addEventListener(LastFmEvent.ARTIST_UPDATE, onChartsUpdate);
      _charts.addEventListener(LastFmEvent.ARTIST_NOT_FOUND, onArtistNotFound);
      _charts.addEventListener(LastFmEvent.TRACK_UPDATE, onSongsUpdate);
      _charts.addEventListener(LastFmEvent.RECENT_TRACKS_UPDATE, onRecentTracksUpdate);
      _charts.addEventListener(LastFmEvent.ERROR, onError);

      var str:String = RemoteVars.getVar(RemoteVars.LASTFM_SESKEY);
      if (0 < str.length)
      {
        var username:String = str.substr(0, str.length - 32);
        _charts.loadRecentTracks(username, MAX_RECENT_TRACKS);
        _charts.loadBannedTracks(username);
      }
      _charts.loadInfo(artist);
    }

    public function next():void
    {
      trace("Radio.next");
      if (null == _charts || null == _played)
      {
        trace("Radio: the radio isn't started.");
        return;
      }

      nextSong();
    }
  }

}